package com.dog.modules.iot.util;

import javax.crypto.KeyAgreement;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPublicKeySpec;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class DiffieHellman {

	private static final String TAG = DiffieHellman.class.getSimpleName();
	private static final String ALGORITHM = "DH";

	private final BigInteger p = new BigInteger(
		        "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
		        +"9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0"
		        +"13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
		        +"98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0"
		        +"A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
		        +"DF1FB2BC2E4A4371", 16);

	private final BigInteger g = new BigInteger(
		        "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
		        +"D6406CFF14266D31266FEA1E5C41564B777E690F5504F213"
		        +"160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
		        +"909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A"
		        +"D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
		        +"855E6EEB22B3B2E5", 16);

//		    private val Q = BigInteger("F518AA8781A8DF278ABA4E7D64B7CB9D49462353", 16)

	private byte[] secretKey;
	private final PublicKey publicKey;
	private final KeyPair kp;
	private final KeyAgreement ka;
	private final byte[] iv = new byte[16];

	public DiffieHellman() throws Exception {
		
		KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);

		DHParameterSpec dhSpec = new DHParameterSpec(p, g);

		keyGen.initialize(dhSpec);

		kp = keyGen.generateKeyPair();

		ka = KeyAgreement.getInstance(ALGORITHM);
		
		ka.init(kp.getPrivate());

		publicKey = kp.getPublic();
		
		byte[] dhPublicKey = ((DHPublicKey)kp.getPublic()).getY().toByteArray();
		if (dhPublicKey.length != 129 && dhPublicKey.length != 128) {
			throw new Exception("DH密钥非法");
		}

		SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmssSS");
		String timestamp = formatter.format(new Date());

//		Integer intTimestamp = Integer.valueOf(timestamp);
		Long intTimestamp = Long.valueOf(timestamp);
		
		for (int i = 0;i < iv.length;i ++) {
			iv[i] = (byte)(timestamp.charAt(iv.length - i - 1) * (new Random(intTimestamp)).nextInt());
		}
	}

	public boolean setReceivedPublicKey(byte[] receivedPublicKey) {
		try {
			BigInteger y = new BigInteger(receivedPublicKey);
			DHPublicKeySpec keySpec = new DHPublicKeySpec(y, p, g);
//			DHPublicKeySpec keySpec = getDHPublicKeySpec(receivedPublicKey);
			KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
			ka.doPhase(keyFactory.generatePublic(keySpec), true);
			byte[] key = ka.generateSecret();
			secretKey = SHA256.getSha256(key);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public byte[] getSecretKey() {
		return secretKey;
	}

	public byte[] getPublicKey() {
		DHPublicKey dhpk = (DHPublicKey)publicKey;
		byte[] array = dhpk.getY().toByteArray();
		byte[] data = new byte[128];
		if (array.length > data.length) {
			System.arraycopy(array, array.length - data.length, data, 0, data.length);
			return data;
		} else {
			return array;
		}
	}

	public byte[] getIv() {
		return iv;
	}

//	private DHPublicKeySpec getDHPublicKeySpec(byte[] publicKeyBytes) {
//		BigInteger y = new BigInteger(publicKeyBytes);
//		return new DHPublicKeySpec(y, P, G);
//	}

}
